package com.lyy.cloud.utils;

import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpStatus;
import org.apache.http.NameValuePair;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.BasicCookieStore;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.impl.cookie.BasicClientCookie;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.ssl.SSLContextBuilder;
import org.apache.http.ssl.TrustStrategy;
import org.apache.http.util.EntityUtils;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * HttpClient4.3工具类
 * @author hang.luo
 */
@Slf4j
public class HttpUtil {

    private static RequestConfig requestConfig = null;
    
    private static final String HTTP = "http";
    private static final String HTTPS = "https";
    private static SSLConnectionSocketFactory sslsf = null;
    private static PoolingHttpClientConnectionManager cm = null;
    private static SSLContextBuilder builder = null;
    static {
        try {
            builder = new SSLContextBuilder();
            // 全部信任 不做身份鉴定
            builder.loadTrustMaterial(null, new TrustStrategy() {
                @Override
                public boolean isTrusted(X509Certificate[] x509Certificates, String s)  {
                    return true;
                }
            });
            sslsf = new SSLConnectionSocketFactory(builder.build(), new String[]{"SSLv2Hello", "SSLv3", "TLSv1", "TLSv1.2"}, null, NoopHostnameVerifier.INSTANCE);
            Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create()
                    .register(HTTP, new PlainConnectionSocketFactory())
                    .register(HTTPS, sslsf)
                    .build();
            cm = new PoolingHttpClientConnectionManager(registry);
            cm.setMaxTotal(200);//max connection
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    static
    {
        // 设置请求和传输超时时间
        requestConfig = RequestConfig.custom().setSocketTimeout(2000).setConnectTimeout(2000).build();
    }
    
    /** 
     * 发送 http post 请求，参数以form表单键值对的形式提交。 
     */  
    public static JSONObject httpPostForm(String url,JSONObject params, Map<String,String> headers,String encode){  
        if(encode == null){  
            encode = "utf-8";  
        }
        //getHttpClient()等价于 HttpClientBuilder.create().build();   
        CloseableHttpClient closeableHttpClient = null;
		try {
			closeableHttpClient = getHttpClient();
		} catch (Exception e2) {
		    log.error("httpPostForm",e2);
		    return null;
		}   
        HttpPost httPost = new HttpPost(url);
        
        //设置header
        if (headers != null && headers.size() > 0) {
            for (Map.Entry<String, String> entry : headers.entrySet()) {
                httPost.setHeader(entry.getKey(),entry.getValue());
            }
        }
        //组织请求参数  
        List<NameValuePair> paramList = new ArrayList <NameValuePair>();  
        if(params != null && params.size() > 0){
            Set<String> keySet = params.keySet();  
            for(String key : keySet) {  
                paramList.add(new BasicNameValuePair(key, params.getString(key)));  
            }  
        }
        try {  
            httPost.setEntity(new UrlEncodedFormEntity(paramList, encode));
        } catch (UnsupportedEncodingException e1) {  
            e1.printStackTrace();  
        }
        JSONObject jsonResult = null;
        String content = null;  
        CloseableHttpResponse  httpResponse = null;
        try {  
            httpResponse = closeableHttpClient.execute(httPost);
            HttpEntity entity = httpResponse.getEntity();  
            content = EntityUtils.toString(entity, encode);  
            jsonResult = JSONObject.parseObject(content);
        } catch (Exception e) {  
            log.error("加载数据错误",e);
        }finally{  
            try {  
            	if(httpResponse!=null){
                    httpResponse.close();
                }
            } catch (IOException e) {
                log.error("关闭连接异常",e);
            }  
        }  
        try {  //关闭连接、释放资源  
            closeableHttpClient.close();  
        } catch (IOException e) {
            log.error("释放资源异常",e);
        }    
        return jsonResult;  
    }
    /**
     * post请求传输json参数
     * @param url  url地址
     * @param jsonParam 参数
     * @return
     */
    public static JSONObject httpPostBody(String url, String jsonParam)
    {
        // post请求返回结果
    	CloseableHttpClient httpClient = null;
		try {
			httpClient = getHttpClient();
		} catch (Exception e2) {
            log.error("httpPostBody",e2);
            return null;
		}   
        JSONObject jsonResult = null;
        HttpPost httpPost = new HttpPost(url);
        // 设置请求和传输超时时间
        httpPost.setConfig(requestConfig);
        try
        {
            if (null != jsonParam)
            {
                // 解决中文乱码问题
                StringEntity entity = new StringEntity(jsonParam, "utf-8");
                entity.setContentEncoding("UTF-8");
                entity.setContentType("application/json");
                httpPost.setEntity(entity);
            }
            CloseableHttpResponse result = httpClient.execute(httpPost);
            // 请求发送成功，并得到响应
            if (result.getStatusLine().getStatusCode() == HttpStatus.SC_OK)
            {
                String str = "";
                try{
                    // 读取服务器返回过来的json字符串数据
                    str = EntityUtils.toString(result.getEntity(), "utf-8");
                    // 把json字符串转换成json对象
                    jsonResult = JSONObject.parseObject(str);
                }catch (Exception e){
                    log.error("post请求提交失败:" + url, e);
                }
            }
        } catch (IOException e){
            log.error("post请求提交失败:" + url, e);
        } finally {
            httpPost.releaseConnection();
        }
        return jsonResult;
    }
    
    /**
     * post请求传输json参数
     * @param url  url地址
     * @param jsonParam 参数
     * @return
     */
    public static JSONObject httpPost(String url, JSONObject jsonParam)
    {
         // post请求返回结果
    	CloseableHttpClient httpClient = null;
		try {
			httpClient = getHttpClient();
		} catch (Exception e2) {
            log.error("httpPostBody",e2);
            return null;
		} 
        JSONObject jsonResult = null;
        HttpPost httpPost = new HttpPost(url);
        // 设置请求和传输超时时间
        httpPost.setConfig(requestConfig);
        try
        {
            if (null != jsonParam)
            {
                // 解决中文乱码问题
                StringEntity entity = new StringEntity(jsonParam.toString(), "utf-8");
                entity.setContentEncoding("UTF-8");
                entity.setContentType("application/json");
                httpPost.setEntity(entity);
            }
            CloseableHttpResponse result = httpClient.execute(httpPost);
            // 请求发送成功，并得到响应
            if (result.getStatusLine().getStatusCode() == HttpStatus.SC_OK)
            {
                String str = "";
                try {
                    // 读取服务器返回过来的json字符串数据
                    str = EntityUtils.toString(result.getEntity(), "utf-8");
                    // 把json字符串转换成json对象
                    jsonResult = JSONObject.parseObject(str);
                } catch (Exception e) {
                    log.error("post请求提交失败:" + url, e);
                }
            }
        } catch (IOException e) {
            log.error("post请求提交失败:" + url, e);
        } finally {
            httpPost.releaseConnection();
        }
        return jsonResult;
    }

    /**
     * post请求传输String参数 例如：name=Jack&sex=1&type=2
     * Content-type:application/x-www-form-urlencoded
     * @param url            url地址
     * @param strParam       参数
     * @return
     */
    public static JSONObject httpPost(String url, String strParam)
    {
    	 // post请求返回结果
    	CloseableHttpClient httpClient = null;
		try {
			httpClient = getHttpClient();
		} catch (Exception e2) {
            log.error("httpPost",e2);
            return null;
		} 
        JSONObject jsonResult = null;
        HttpPost httpPost = new HttpPost(url);
        httpPost.setConfig(requestConfig);
        try {
            if (null != strParam) {
                // 解决中文乱码问题
                StringEntity entity = new StringEntity(strParam, "utf-8");
                entity.setContentEncoding("UTF-8");
                entity.setContentType("application/x-www-form-urlencoded");
                httpPost.setEntity(entity);
            }
            CloseableHttpResponse result = httpClient.execute(httpPost);
            // 请求发送成功，并得到响应
            if (result.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
                String str = "";
                try {
                    // 读取服务器返回过来的json字符串数据
                    str = EntityUtils.toString(result.getEntity(), "utf-8");
                    // 把json字符串转换成json对象
                    jsonResult = JSONObject.parseObject(str);
                } catch (Exception e) {
                    log.error("post请求提交失败:" + url, e);
                }
            }
        } catch (IOException e) {
            log.error("post请求提交失败:" + url, e);
        } finally {
            httpPost.releaseConnection();
        }
        return jsonResult;
    }
    
    public static CloseableHttpClient getHttpClient() throws Exception {
        CloseableHttpClient httpClient = HttpClients.custom()
                .setSSLSocketFactory(sslsf)
                .setConnectionManager(cm)
                .setConnectionManagerShared(true)
                .build();
        return httpClient;
    }
    
    public static CloseableHttpClient getHttpClient(Cookie[] cookies) throws Exception {
    	HttpClientBuilder builder = HttpClients.custom();
    	if(cookies!=null) {
    		BasicCookieStore cookieStore = new BasicCookieStore();
    		
    		BasicClientCookie[] storeCookies = new BasicClientCookie[cookies.length];
    		int i = 0;
    		for(Cookie cookie:cookies) {
    			BasicClientCookie c = new BasicClientCookie(cookie.getName(),cookie.getValue());
    			c.setVersion(cookie.getVersion());
    			if(StringUtils.isNotBlank(cookie.getDomain())) {
    				c.setDomain(cookie.getDomain());
    			}else {
    				//c.setDomain("/");
    			}
    	    	
    	    	c.setPath(cookie.getPath());
    	    	storeCookies[i++] = c;
    		}
    		cookieStore.addCookies(storeCookies);
    		builder.setDefaultCookieStore(cookieStore);
    	}
    	CloseableHttpClient httpClient = builder
    			.setSSLSocketFactory(sslsf)
    			.setConnectionManager(cm)
    			.setConnectionManagerShared(true)
    			.build();
    	return httpClient;
    }
    
    /**
     * 发送get请求
     * @param url 路径
     * @return
     */
    public static String httpGetStr(String url,Cookie[] cookies)
    {
        // get请求返回结果
        String str = null;
        // post请求返回结果
    	CloseableHttpClient client = null;
		try {
			client = getHttpClient(cookies);
		} catch (Exception e2) {
            log.error("httpGetStr",e2);
            return null;
		} 
        // 发送get请求
        HttpGet request = new HttpGet(url);
        request.setConfig(requestConfig);
        try
        {
            CloseableHttpResponse response = client.execute(request);

            // 请求发送成功，并得到响应
            if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
                // 读取服务器返回过来的json字符串数据
                HttpEntity entity = response.getEntity();
                str = EntityUtils.toString(entity, "utf-8");
            } else {
                log.error("get请求提交失败:" + url);
            }
        } catch (IOException e) {
            log.error("get请求提交失败:" + url, e);
        } finally {
            request.releaseConnection();
        }
        return str;
    }

    /**
     * 发送get请求
     * @param url 路径
     * @return
     */
    public static String httpGetStr(String url)
    {
        // get请求返回结果
        String str = null;
        // post请求返回结果
    	CloseableHttpClient client = null;
		try {
			client = getHttpClient();
		} catch (Exception e2) {
            log.error("httpGetStr",e2);
            return null;
		} 
        // 发送get请求
        HttpGet request = new HttpGet(url);
        request.setConfig(requestConfig);
        try {
            CloseableHttpResponse response = client.execute(request);

            // 请求发送成功，并得到响应
            if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
                // 读取服务器返回过来的json字符串数据
                HttpEntity entity = response.getEntity();
                str = EntityUtils.toString(entity, "utf-8");
            } else {
                log.error("get请求提交失败:" + url);
            }
        } catch (IOException e) {
            log.error("get请求提交失败:" + url, e);
        } finally {
            request.releaseConnection();
        }
        return str;
    }

    /**
     * 发送get请求
     * @param url 路径
     * @return
     */
    public static JSONObject httpGet(String url)
    {
    	String strResult = httpGetStr(url);
        // get请求返回结果
        JSONObject jsonResult = JSONObject.parseObject(strResult);;

        return jsonResult;
    }
    
    /**
     * 发送get请求
     * @return
     */
    public static String getQueryString(HttpServletRequest request)
    {
    	Enumeration<String> paras= request.getParameterNames();
		StringBuffer sbf = new StringBuffer();
		while(paras.hasMoreElements()) {
			String paraName = paras.nextElement();
			String value = request.getParameter(paraName);
			try {
				sbf.append("&").append(paraName).append("=").append(URLEncoder.encode(value,"utf8"));
			} catch (UnsupportedEncodingException e) {
				e.printStackTrace();
			}
		}
		if(sbf.length()>0) {
			sbf.deleteCharAt(0);
		}
		String str = sbf.toString();
	
		return str;
    }
    

}